pelco协议及其实现的简单认识

您所在的位置:网站首页 Android 云台控制485 pelco协议及其实现的简单认识

pelco协议及其实现的简单认识

2024-06-05 01:00| 来源: 网络整理| 查看: 265

在搞visca的同时顺便也搞了pelco。这里再做个笔记。pelco,中文翻译为“派尔高”,在行文和写代码过程,写pelco比写“派尔高”快很多,所以一般就写pelco。这个协议在云台控制中用得比较多,比较出名的有PTZ,用rs232或rs485来通信。

pelco有两种协议,D协议和P协议,两者命令封装不太一样,网上有协议的说明文档,也有实现的代码,我找到一个C#写的,某搜索引擎上找得到的介绍派尔高协议的,基本上都是直接把每个命令的数据一一写成数组来调用,个人认为这样不太方便。本文所讲的是pelco D协议。

一、命令格式

文档中说pelco D协议的命令都是7个字节的(实际上,有些不是),命令格式如下图:说明:字节1:D协议同步头为0xFF。字节2:相机编号(或称地址),范围为1~0xFF,0x01表示相机1。字节3:CMND1,命令1。字节4:CMND2,命令2。作为扩展命令,命令数值为奇数。字节5:数据字节1,作为motion命令,其表示pan的速度。字节6:数据字节2,作为motion命令,其表示tilt的速度。字节7:检验码,计算公式:(字节2+字节3+字节4+字节5+字节6)% 0x100。注:检验码是除了同步头及本身(CKSM)字节外的所有字节的的和,再除以265,取余数(用“%”即可)。

命令共2大类,motion命令,和非motion命令(注:可以称为基本命令和扩展命令/高级命令)。其中motion命令,在CMND2中Bit0始终为0。反之,该比特为1表示非motion命令。motion命令包含了水平移动、垂直移动、光圈、变焦、对焦等功能。这类命令是由命令1和命令2的各个位来表示的。如下图:要实现某一项功能,只要在对应的位置设为1即可,有些命令是可以同时设置的,但有些是不行的,比如,可以同时实现左(右)转和向上(下)转动,但不能同时左转及右转(两者是互斥的)。Bit7含义为“sense bit”(sense一词,在linux内核中使用比较多,我其实也搞不明白这个词中文该怎么表达),它决定了Bit4和Bit3的含义。如下图所示:其实说白了,就是这3个比特的哪些组合可以控制相机上断电,自动扫描,哪些无效,等等。说到这里,想起来了公司某部门发的一个邮件,说某客户想接入云台,是用派尔高协议来控制的,然后还顺带一个中文的协议文档,这个文档翻译得不伦不类,应该是机器翻译的,把“sense bit”翻译成“感觉字节”,一开始看中文文档时,完全一头雾水,后面经过努力,上网上查了英文原版,才有点理解。所以,有时候,看英文原版获取的资源更通俗,更准确。

二、响应

相机返回的响应包有4种,0字节、4字节、7字节、18字节。除了第一种外,其它每种都和上面给出的命令格式相似,同步头+相机地址+信息体+检验码。文档中有每种响应包的具体格式的描述,如果格式来解析即可得到想要的数据。文档中说大部分命令是有返回值的——像上面的motion命令,也有响应包,但我实际测试的结果,串口是没有返回什么数据的,或者是我拿到的那个东西本身就是这样的。

三、协议文档备注

协议文档中每条命令都讲得比较细,不过,有部分命令是厂家自己实现的,比如,有些命令超过7个字节,这跟协议上讲的有冲突,但实际上却是可以的。这个主要是看厂家提供的协议文档了。说到这,不得不提现在我接手的这个任务,厂家提供的文档惜墨如金,不肯多写一点字,文档又不规范,东写一点,西写一点,给的文档也不全,有些命令还要问人家才知道。

四、实现

为了方便,专门为pelco通信定义了PELCOPacket_t结构体(其实它和上一篇文章的visca那个结构体是同一个东西),命令封装如下:

1234567891011121314void _pelco_append_byte(PELCOPacket_t *packet, unsigned char byte){ packet->bytes[packet->length]=byte; (packet->length)++;} void _pelco_init_packet(PELCOPacket_t *packet){ // set it to null memset(packet->bytes, '\0', sizeof(packet->bytes)); // we start writing at byte 2, the first byte and the second will be filled by the // packet sending function(_pelco_send_packet). This function will also append a cksm. packet->length = 2;}

注意,初始化时,命令包的长度是2,因为pelco协议的真正数据是从第2个字节开始的,这让调用者关注的是真正的数据,而不用理会同步头、相机地址等信息。命令发送如下:

1234567891011121314151617181920212223242526272829303132// All commands are 7 bytes long in D Protocolint _pelco_send_packet(PELCOInterface_t *iface, PELCOPacket_t *packet){ int cksm = 0; int i = 0; // check data: if (iface->address>0xff) { return PELCO_FAILURE; } // build header: packet->bytes[0] = 0xff; packet->bytes[1] = iface->address; // see spec, some cmd has 7 bytes, some has 9 bytes for (i = 0; i < packet->length; i++) { cksm += packet->bytes[1+i]; } cksm = cksm % 0x100; /* cksm = (packet->bytes[1] + packet->bytes[2] + packet->bytes[3] + packet->bytes[4] + packet->bytes[5]) % 0x100; */ // append footer(cksm) _pelco_append_byte(packet,cksm); return _pelco_write_packet_data(iface,packet); }

因为有些命令不只有7个字节,所以这里用for循环计算每个需要计算的字节,而不是指定哪一些字节被计算。 命令的封装接口比较简单,基本上和visca一样,比如,像stop命令,就是所有的信息体都搞成0就行了。

123456789101112int pelco_camera_stop(PELCOInterface_t *iface){ PELCOPacket_t packet; _pelco_init_packet(&packet); _pelco_append_byte(&packet,0x00); _pelco_append_byte(&packet,0x00); _pelco_append_byte(&packet,0x00); _pelco_append_byte(&packet,0x00); return _pelco_send_packet_no_reply(iface, &packet);}

参考资源:1、一个C#实现的工程:http://www.codeproject.com/Articles/8034/Pelco-P-and-D-protocol-implementation-in-C2、一个图文并茂的示例:http://www.commfront.com/RS232_Examples/CCTV/Pelco_D_Pelco_P_Examples_Tutorial.HTM

后记:本文出现很多次“搞”,近来的确是东搞西搞,人在公司,身不由己。本文仅对协议进行描述,不贴出实际的实现代码。

李迟记于2014年7月3日



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3